#include "streamingexportmanager.h"
#include "unifiedpagerenderer.h"
#include "unifiedcachemanager.h"
#include "fileidentitymanager.h"
#include "layoutstatemanager.h"
#include "configmanager.h"
#include "dpiservice.h"
#include "watermark.h"

#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QPdfWriter>
#include <QPainter>
#include <QPageSize>
#include <QMarginsF>
#include <QMetaObject>
#include <QImageReader>

#include <cpp/poppler-document.h>
#include <cpp/poppler-page.h>
#include <cpp/poppler-image.h>
#include <cpp/poppler-page-renderer.h>

StreamingExportManager::StreamingExportManager(QObject* parent)
    : QObject(parent)
    , m_isExporting(0)
    , m_cancelRequested(0)
    , m_exportThread(nullptr)
    , m_renderer(nullptr)
    , m_cacheManager(nullptr)
{
    
    // ✅ 创建独立的渲染器（线程安全，避免与主窗口冲突）
    m_renderer = new UnifiedPageRenderer(this);
    
    // ✅ 使用缓存管理器单例（公用，线程安全）
    m_cacheManager = UnifiedCacheManager::instance();
    
}

StreamingExportManager::~StreamingExportManager()
{
    
    // 确保线程已退出
    if (m_exportThread && m_exportThread->isRunning()) {
        m_cancelRequested.storeRelease(1);
        m_exportThread->wait(3000);
    }
    
    // 渲染器会自动删除（父对象管理）
    // 缓存管理器是单例，不需要删除
    
}

void StreamingExportManager::startExport(
    const QList<UnifiedFileInfo>& files,
    const ProcessingSettings& settings,
    const QString& outputPath)
{

    // 1. 验证依赖组件
    if (!m_renderer) {
        qWarning() << "[StreamingExport] 渲染器未初始化";
        emit exportFailed("渲染器未初始化");
        return;
    }
    
    if (!m_cacheManager) {
        qWarning() << "[StreamingExport] 缓存管理器未初始化";
        emit exportFailed("缓存管理器未初始化");
        return;
    }
    

    // 2. 幂等性检查：原子切换状态
    int expected = 0;
    if (!m_isExporting.testAndSetOrdered(expected, 1)) {
        qWarning() << "[StreamingExport] Already exporting, reject";
        emit exportFailed("已有导出任务在运行，请稍后再试");
        return;
    }

    // 3. 参数校验
    if (files.isEmpty()) {
        m_isExporting.storeRelease(0);
        emit exportFailed("没有文件需要导出");
        return;
    }

    // 4. 重置取消标志
    m_cancelRequested.storeRelease(0);

    // 5. 保存设置副本并设置到渲染器（导出专用设置）
    m_settings = settings;
    m_renderer->setRenderSettings(settings);  // ✅ 设置导出DPI等参数

    // 6. 发送开始信号
    emit exportStarted(files.size(), outputPath);

    // 7. 创建导出线程（唯一线程）
    m_exportThread = QThread::create([this, files, settings, outputPath]() {
        
        // 调用核心导出循环
        exportLoop(files, settings, outputPath);
        
    });

    // 8. 连接线程完成信号
    connect(m_exportThread, &QThread::finished, this, [this]() {
        if (m_exportThread) {
            m_exportThread->deleteLater();
            m_exportThread = nullptr;
        }
        
        // 重置状态
        m_isExporting.storeRelease(0);
    });

    // 9. 启动线程
    m_exportThread->start();
}

void StreamingExportManager::exportLoop(
    const QList<UnifiedFileInfo>& files,
    const ProcessingSettings& settings,
    const QString& outputPath)
{

    // 1. 确保输出目录存在
    QFileInfo outputInfo(outputPath);
    QDir outputDir = outputInfo.absoluteDir();
    if (!outputDir.exists()) {
        if (!outputDir.mkpath(".")) {
            QMetaObject::invokeMethod(this, "exportFailed", Qt::QueuedConnection,
                                    Q_ARG(QString, "无法创建输出目录"));
            return;
        }
    }

    // 2. 删除已存在的输出文件
    if (QFile::exists(outputPath)) {
        QFile::remove(outputPath);
    }

    // 3. 创建PDF写入器（使用导出DPI）
    QPdfWriter pdfWriter(outputPath);
    pdfWriter.setPageSize(QPageSize::A4);
    pdfWriter.setPageMargins(QMarginsF(0, 0, 0, 0));
    pdfWriter.setResolution(settings.standardDPI);  // ✅ 导出DPI
    pdfWriter.setCreator("LongImageReader - Streaming Export");
    pdfWriter.setTitle(QString("Merged Export (DPI=%1)").arg(settings.standardDPI));

    // 4. 创建画笔
    QPainter painter(&pdfWriter);
    if (!painter.isActive()) {
        QMetaObject::invokeMethod(this, "exportFailed", Qt::QueuedConnection,
                                Q_ARG(QString, "无法创建PDF写入器"));
        return;
    }

    // 5. 🔧 优化：直接从GlobalPageManager获取总页数，消除计算阶段
    int totalDisplayPages = GlobalPageManager::instance().getTotalGlobalPages();
    int totalFiles = files.size();


    if (totalDisplayPages <= 0) {
        qWarning() << "[StreamingExport] 总页数为0，无法导出";
        QMetaObject::invokeMethod(this, "exportFailed", Qt::QueuedConnection,
                                Q_ARG(QString, "没有有效的页面可以导出"));
        return;
    }

    // 🔧 修复：移除开始导出的0%进度信号，让进度条从第一页开始显示

    // 6. 流式导出：逐文件加载和写入（模拟用户操作）
    int globalPageNumber = 1;
    bool firstPage = true;

    for (int fileIndex = 0; fileIndex < files.size(); ++fileIndex) {
        // ✅ 每个文件前检查取消
        if (shouldCancel()) {
            painter.end();
            QFile::remove(outputPath);
            QMetaObject::invokeMethod(this, "exportCancelled", Qt::QueuedConnection);
            return;
        }

        const UnifiedFileInfo& file = files[fileIndex];

        // 🔧 修复：移除文件级别进度信号，避免与页面级进度冲突
        // 只保留页面级别的精确进度，确保进度条线性增长

        // 7. 加载该文件的所有显示页（模拟用户浏览文件）
        QList<QImage> displayPages = loadDisplayPagesForFile(file, settings);

        // 8. 逐页导出（模拟用户翻页）
        for (int pageIndex = 0; pageIndex < displayPages.size(); ++pageIndex) {
            // ✅ 每页检查取消
            if (shouldCancel()) {
                painter.end();
                QFile::remove(outputPath);
                QMetaObject::invokeMethod(this, "exportCancelled", Qt::QueuedConnection);
                return;
            }

            // 🔍 调试：记录页面处理开始时间
            qint64 pageStartTime = QDateTime::currentMSecsSinceEpoch();

            const QImage& pageImage = displayPages[pageIndex];
            if (pageImage.isNull()) {
                qWarning() << "[StreamingExport] 页面" << pageIndex << "为空，跳过";
                continue;
            }

            // 9. 切换到新页
            if (!firstPage) {
                qint64 newPageTime = QDateTime::currentMSecsSinceEpoch();
                pdfWriter.newPage();
            }
            firstPage = false;

            // 10. 渲染到PDF（区别只是画布）
            qint64 renderStartTime = QDateTime::currentMSecsSinceEpoch();
            renderPageToPDF(pageImage, painter, pdfWriter, globalPageNumber, totalDisplayPages);
            qint64 renderEndTime = QDateTime::currentMSecsSinceEpoch();

            // 11. 🔧 优化：简化进度计算，使用线性进度 (0-99%)
            // 确保0-99%的完整线性范围，让用户看到完整的进度
            int exportProgress = (globalPageNumber * 99) / totalDisplayPages;  // 0-99%，线性计算

            // 🔍 调试：记录进度信号发送时间
            qint64 signalStartTime = QDateTime::currentMSecsSinceEpoch();

            // 🔧 优化：使用QueuedConnection确保UI线程非阻塞更新，只传递百分比进度
            QMetaObject::invokeMethod(this, [this, exportProgress, signalStartTime]() {
                qint64 receiveTime = QDateTime::currentMSecsSinceEpoch();
                emit progressUpdated(exportProgress, 100, QString());  // 空字符串，不显示文字信息
            }, Qt::QueuedConnection);

            // 🔧 修复：每页都强制刷新UI，确保进度及时显示
            QMetaObject::invokeMethod(this, [this]() {
                qint64 refreshTime = QDateTime::currentMSecsSinceEpoch();
                // 立即处理UI事件，防止信号积压
                if (qApp) {
                    qApp->processEvents(QEventLoop::AllEvents, 5); // 最多处理5ms
                }
            }, Qt::QueuedConnection);

            // 🔧 优化：每10页后添加极短延迟，让UI线程有时间处理更新
            if (globalPageNumber % 10 == 0) {
                QThread::msleep(1); // 1毫秒延迟，给UI线程喘息时间
            }

            // 🔍 调试：记录页面处理完成的总耗时
            qint64 pageEndTime = QDateTime::currentMSecsSinceEpoch();
            qint64 pageTotalTime = pageEndTime - pageStartTime;

            globalPageNumber++;
        }

        // 12. 释放该文件的所有显示页（流式处理）
        displayPages.clear();
    }

    // 13. 完成绘制
    painter.end();

    // 14. 发送100%完成进度信号
    qint64 completeTime = QDateTime::currentMSecsSinceEpoch();
    QMetaObject::invokeMethod(this, "progressUpdated", Qt::QueuedConnection,
                            Q_ARG(int, 100), Q_ARG(int, 100), Q_ARG(QString, QString()));  // 空字符串，不显示文字信息

    // 🔧 修复：确保100%进度显示后再发送完成信号
    QMetaObject::invokeMethod(this, [this, outputPath]() {

        // 15. 最终检查
        if (shouldCancel()) {
            QFile::remove(outputPath);
            QMetaObject::invokeMethod(this, "exportCancelled", Qt::QueuedConnection);
        } else {
            QMetaObject::invokeMethod(this, "exportCompleted", Qt::QueuedConnection,
                                    Q_ARG(QString, outputPath));
        }
    }, Qt::QueuedConnection);
}

// ========== 新实现：完全模拟 MainWindow 的页面加载逻辑 ==========

QList<QImage> StreamingExportManager::loadDisplayPagesForFile(
    const UnifiedFileInfo& file,
    const ProcessingSettings& settings)
{
    
    QList<QImage> displayPages;
    
    // 获取文件标识和布局模式
    QString fileIdentity = FileIdentityManager::getFileIdentity(file.filePath);
    LayoutMode layoutMode = LayoutStateManager::instance()->getFileLayoutMode(fileIdentity);
    
    
    if (!m_cacheManager) {
        qWarning() << "[StreamingExport] CacheManager 未设置";
        return displayPages;
    }
    
    if (!m_renderer) {
        qWarning() << "[StreamingExport] Renderer 未设置";
        return displayPages;
    }
    
    // 步骤 1：从缓存加载所有原始切片（单列页面）
    QList<QImage> originalSlices;
    for (int pageIndex = 0; pageIndex < file.pageCount; ++pageIndex) {
        if (shouldCancel()) {
            break;
        }
        
        QImage pageImage = m_cacheManager->loadFromCache(fileIdentity, pageIndex);
        
        if (!pageImage.isNull()) {
            originalSlices.append(pageImage);
        } else {
            qWarning() << "[StreamingExport] ❌ 原始切片" << pageIndex << "不在缓存中";
            // 加载失败时创建占位符
            QImage placeholder(800, 600, QImage::Format_RGB32);
            placeholder.fill(QColor(240, 240, 240));
            originalSlices.append(placeholder);
        }
    }
    
    
    // 步骤 2：根据布局模式重新组合（与主窗口显示相同）
    if (layoutMode == LayoutMode::SingleColumn) {
        // 单列模式：不需要组合，直接使用原始切片
        displayPages = originalSlices;
    } else {
        // 多列模式：使用 UnifiedPageRenderer 组合（与主窗口相同）
        auto layout = m_renderer->rearrangeWithLayout(originalSlices, layoutMode);
        displayPages = layout.pages;
        
        int pagesPerComposite = m_renderer->pagesPerComposite(layoutMode);
    }
    
    return displayPages;
}



void StreamingExportManager::renderPageToPDF(
    const QImage& page,
    QPainter& painter,
    QPdfWriter& pdfWriter,
    int globalPageNumber,
    int totalPages)
{
    if (m_renderer) {
        // ✅ 使用新的双画布接口（推荐）
        // 直接传入页面内容，渲染器会处理页码、边距等
        m_renderer->renderToPDF(&pdfWriter, &painter, page, globalPageNumber, totalPages);

    } else {
        // 降级方案：简单渲染（居中缩放）
        QRect pageRect = painter.viewport();
        QSize scaledSize = page.size().scaled(pageRect.size(), Qt::KeepAspectRatio);
        QRect targetRect(0, 0, scaledSize.width(), scaledSize.height());
        targetRect.moveCenter(pageRect.center());
        painter.drawImage(targetRect, page);

    }

    // 🔧 新增：添加水印逻辑（参考MergedExportManager实现）
    QString authToken = ConfigManager::getAuthToken();
    if (authToken.isEmpty()) {

        painter.save();

        // 设置水印字体和样式（与MergedExportManager保持一致）
        QFont watermarkFont("Microsoft YaHei", 36, QFont::Bold);
        painter.setFont(watermarkFont);
        painter.setPen(QColor(200, 200, 200, 120));
        painter.setRenderHint(QPainter::Antialiasing, true);

        // 计算水印位置（3x3网格布局）
        QRect pdfPageRect = painter.viewport();
        int watermarkWidth = pdfPageRect.width() / 3;
        int watermarkHeight = pdfPageRect.height() / 3;
        QString watermarkText = "影谷长图处理大师";

        // 3x3网格水印（无内层取消检查，水印绘制很快）
        for (int row = 0; row < 3; ++row) {
            for (int col = 0; col < 3; ++col) {
                int x = col * watermarkWidth + watermarkWidth / 2;
                int y = row * watermarkHeight + watermarkHeight / 2;

                painter.save();
                painter.translate(x, y);
                painter.rotate(45);

                QRect textRect = painter.fontMetrics().boundingRect(watermarkText);
                textRect.moveCenter(QPoint(0, 0));
                painter.drawText(textRect, Qt::AlignCenter, watermarkText);

                painter.restore();
            }
        }

        painter.restore();
    } else {
    }
}

void StreamingExportManager::cancelExport()
{

    // 1. 幂等性检查：如果不在导出，直接返回
    if (!m_isExporting.loadAcquire()) {
        return;
    }

    // 2. 设置取消标志（线程会在每页检查并退出）
    m_cancelRequested.storeRelease(1);

    // 3. 等待线程退出（最多3秒）
    if (m_exportThread && m_exportThread->isRunning()) {

        if (!m_exportThread->wait(3000)) {
            qWarning() << "[StreamingExport] Thread did not exit in 3s";
            // 不强制终止，让它自然结束
        } else {
        }
    }

    // 4. 重置状态
    m_isExporting.storeRelease(0);
    m_cancelRequested.storeRelease(0);

}

bool StreamingExportManager::isExporting() const
{
    return m_isExporting.loadAcquire() == 1;
}

int StreamingExportManager::calculateA4HeightInPixels(double dpi) const
{
    // A4高度：297mm
    return static_cast<int>((A4_HEIGHT_MM / MM_TO_INCH) * dpi);
}

void StreamingExportManager::cleanup()
{
    // 清理临时资源（如果有）
}

